package service

import (
	"afupanel/constant"
	"afupanel/dto"
	"errors"
	"time"
	"utility/common"
)

type User struct {
	Id           int64
	CreateTime   time.Time
	UpdateTime   time.Time
	Username     string
	Password     string
	Email        string
	Mobile       string
	Role         string // SUPERADMIN ADMIN USER
	VerifyKey    string // 验证码
	VerifyStatus string // 验证状态 UNVERIFY VERIFIED
	LastLogin    string // 上次登录时间 默认为FIRSTLOGIN
	LastLoginIp  string // 上次登录IP
}

/**
是否存在该角色用户
*/
func Exist(role string) (u User, has bool, err error) {
	has, err = Engine.Where("role = ?", role).Get(&u)
	return
}

/**
查询是否存在该key值未验证的用户
*/
func QueryUserVerifyKeyUnVerified(verifyKey, status string) (has bool, u User, err error) {
	has, err = Engine.Where("verify_key = ?", verifyKey).And("verify_status = ?", status).Get(&u)
	return
}

/**
生成验证值，以及发送验证链接到邮箱
*/
func MakeUserForgetVerifyKey(email string) (err error) {
	if has, u, err := FindUserByEmail(email); err == nil {
		if !has {
			return errors.New("不存在该email的用户无法重置")

		} else {
			//TODO 发送邮件
			u.VerifyKey = common.RandOrderNo()
			u.VerifyStatus = constant.UNVERIFY
			if has, _, err := QueryUserVerifyKeyUnVerified(u.VerifyKey, u.VerifyStatus); err == nil {
				if has {
					// 查询一波，并如果存在，重新生成
					u.VerifyKey = common.RandOrderNo()
				}
			}
			Engine.ID(u.Id).Update(&u)
		}
		return nil
	} else {
		return err
	}
}

func FindUserByVerifyKeyAndStatusIsUnVerifid(verifyKey string) (has bool, u User, err error) {
	has, err = Engine.Where("verify_key = ?", verifyKey).And("verify_status=?", "UNVERIFY").Get(&u)
	return
}

/**
重置密码
*/
func ResetUserPwd(req dto.ResetPwdReq) (err error) {
	if has, u, err := FindUserByVerifyKeyAndStatusIsUnVerifid(req.VerifyKey); err == nil {
		if has {
			u.Password = common.EncryptStrWithSalt(req.NewPwd)
			Engine.ID(u.Id).Update(&u)
		} else {
			// 这里将来需要进行安全检测并将多次尝试的IP禁止访问
			return errors.New("不存在该验证码")
		}
	}
	return nil
}

func FindUserByEmail(email string) (has bool, u User, err error) {
	has, err = Engine.Where("email = ?", email).Get(&u)
	return
}

/**
通过用户名查找用户
*/
func FindUserByUserName(username string) (has bool, u User, err error) {
	has, err = Engine.Where("username = ?", username).Get(&u)
	return
}

func FindUserByUserId(userid int64) (has bool, u User, err error) {
	has, err = Engine.Where("id = ?", userid).Get(&u)
	return
}

/**
修改用户密码
*/
func ChangePassword(username, originpass, newpass string) (err error) {
	if has, u, err := FindUserByUserName(username); err == nil {
		if has {
			if state, err := common.CompareStrToSaltEncryptedStr(originpass, u.Password); err == nil {
				if state {
					u.Password = common.EncryptStrWithSalt(newpass)
					Engine.ID(u.Id).Update(u)
				} else {
					err = errors.New("用户名密码不匹配")
				}
			}
		} else {
			err = errors.New("不存在该用户")
		}
	}
	return
}

func ChangeUserPwd(pwd dto.ChangePwd) (err error) {
	if has, s, err := GetSessionByToken(pwd.Token); err == nil {
		if has {
			if exist, u, err := FindUserByUserId(s.Userid); err != nil {
				if exist {
					// 开始比对密码
					if state, err := common.CompareStrToSaltEncryptedStr(pwd.OriginPwd, u.Password); err == nil {
						if state {
							u.Password = common.EncryptStrWithSalt(pwd.NewPwd)
							Engine.ID(u.Id).Update(u)
						} else {
							err = errors.New("用户名密码不匹配")
						}
					}

				} else {
					return errors.New("不存在该用户，无法更新密码")
				}
			} else {
				return err
			}

		} else {
			return errors.New("用户登陆过期请重新登陆")
		}
		return nil
	} else {
		return err
	}
}

func UpdateLastLoginInfo(u User, ip string) {
	u.LastLogin = common.TimeNowForSecond()
	u.LastLoginIp = ip
	Engine.ID(u.Id).Update(&u)
}

func LoginCheck(req dto.LoginReq) (token string, err error) {
	if has, u, err := FindUserByUserName(req.Username); err == nil {
		if has {
			if state, err := common.CompareStrToSaltEncryptedStr(req.Password, u.Password); err == nil {
				if state {
					token = common.RandOrderNo()
					err = AddSession(u.Id, token, u.Role)
					if err != nil {
						return "", err
					}
					UpdateLastLoginInfo(u, req.ClientIP)
					return token, nil
				} else {
					err = errors.New("用户名密码吧匹配")
					AddBlockIp(req.ClientIP, "USER_NAME_PASSWORD_NOT_MATCH")
					return "", err
				}
			} else {
				return "", err
			}
		} else {
			err = errors.New("该用户不存在")
			return "", err
		}
	}
	return
}

/**
添加默认用户
*/
func AddDefaultUser() {
	if _, has, err := Exist("SUPERADMIN"); err == nil {
		if !has {
			u := User{
				CreateTime: time.Now(),
				UpdateTime: time.Now(),
				Username:   "afupanel",
				Password:   common.EncryptStrWithSalt("AfuPanel888"),
				Role:       "SUPERADMIN",
				LastLogin:  "FIRSTLOGIN",
			}
			Engine.InsertOne(&u)
		}
	}
}
